
package com.jiao.spring_es.controller;

import com.alibaba.fastjson.JSONObject;
import com.jiao.spring_es.client.ElasticSearchClientConnect;
import com.jiao.spring_es.entity.Person;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedTerms;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.elasticsearch.search.aggregations.bucket.terms.Terms.Bucket;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/documents")
public class ElasticsearchDocumentController {

    @Autowired
    private ElasticSearchClientConnect elasticSearchClientConfig;

    /**
     * 添加document
     * @throws IOException
     */
    @PostMapping("/addDocument")
    public IndexResponse addDocument(@RequestBody Person person) throws IOException {
        RestHighLevelClient client = elasticSearchClientConfig.restClient();
        String jsonString = JSONObject.toJSONString(person);
        IndexRequest request = new IndexRequest("jing_index").id("1001").source(jsonString, XContentType.JSON);
        IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);

        // 打印结果
        System.out.println("Index Response: " + indexResponse.getResult());

        return indexResponse;
    }

    /**
     * 查询document
     * @throws IOException
     */
    @GetMapping("/queryDocument")
    public GetResponse queryDocument() throws IOException {
        RestHighLevelClient client = elasticSearchClientConfig.restClient();
        GetRequest request = new GetRequest("jing_index", "1001");
        GetResponse getResponse = client.get(request, RequestOptions.DEFAULT);
        Map<String, Object> source = getResponse.getSource();
        System.out.println("Get source: " + source);
        // 打印结果
        System.out.println("Get Response: " + getResponse.getSourceAsString());

        return getResponse;
    }

    /**
     * 修改document
     * @throws IOException
     */
    @PutMapping("/modifyDocument")
    public UpdateResponse modifyDocument() throws IOException {
        RestHighLevelClient client = elasticSearchClientConfig.restClient();
        Map<String, Object> map = new HashMap<>();
        map.put("name", "java客户端aaa");
        UpdateRequest request = new UpdateRequest("jing_index", "1001").doc(map);
        UpdateResponse updateResponse = client.update(request, RequestOptions.DEFAULT);

        // 打印结果
        System.out.println("Update Response: " + updateResponse.getResult());

        return updateResponse;
    }

    /**
     * 删除document
     * @throws IOException
     */
    @DeleteMapping("/removeDocument")
    public DeleteResponse removeDocument() throws IOException {
        RestHighLevelClient client = elasticSearchClientConfig.restClient();
        DeleteRequest request = new DeleteRequest("jing_index", "1001");
        DeleteResponse deleteResponse = client.delete(request, RequestOptions.DEFAULT);

        // 打印结果
        System.out.println("Delete Response: " + deleteResponse.getResult());

        return deleteResponse;
    }

    /**
     * 批量添加document
     * @throws IOException
     */
    @PostMapping("/batchAddDocument")
    public BulkResponse batchAddDocument() throws IOException {
        RestHighLevelClient client = elasticSearchClientConfig.restClient();
        BulkRequest request = new BulkRequest();

        request.add(new IndexRequest("Person_test").id("1002").source(new Person("test2", "男", 19), XContentType.JSON));
        request.add(new IndexRequest("Person_test").id("1003").source(new Person("test3", "男", 20), XContentType.JSON));
        request.add(new IndexRequest("Person_test").id("1004").source(new Person("test4", "女", 21), XContentType.JSON));

        BulkResponse bulkResponse = client.bulk(request, RequestOptions.DEFAULT);

        // 打印结果
        System.out.println("Bulk Response: " + bulkResponse.getItems());

        return bulkResponse;
    }

    /**
     * 批量删除document
     * @throws IOException
     */
    @DeleteMapping("/batchDeleteDocument")
    public BulkResponse batchDeleteDocument() throws IOException {
        RestHighLevelClient client = elasticSearchClientConfig.restClient();
        BulkRequest request = new BulkRequest();

        request.add(new DeleteRequest("Person_test", "1002"));
        request.add(new DeleteRequest("Person_test", "1003"));

        BulkResponse bulkResponse = client.bulk(request, RequestOptions.DEFAULT);

        // 打印结果
        System.out.println("Bulk Response: " + bulkResponse.getItems());

        return bulkResponse;
    }

    /**
     * 全量查询document
     * @throws IOException
     */
    @GetMapping("/queryAllDocument")
    public SearchResponse queryAllDocument() throws IOException {
        RestHighLevelClient client = elasticSearchClientConfig.restClient();
        SearchRequest request = new SearchRequest("Person_test");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.matchAllQuery());
        request.source(sourceBuilder);

        SearchResponse searchResponse = client.search(request, RequestOptions.DEFAULT);

        // 打印结果
        SearchHits hits = searchResponse.getHits();
        for (SearchHit hit : hits.getHits()) {
            System.out.println("Person = " + hit.getSourceAsString());
        }
        System.out.println("Total Hits: " + hits.getTotalHits().value);

        return searchResponse;
    }

    /**
     * 分页查询document
     * @throws IOException
     */
    @GetMapping("/pagingQueryDocument")
    public SearchResponse pagingQueryDocument() throws IOException {
        RestHighLevelClient client = elasticSearchClientConfig.restClient();
        SearchRequest request = new SearchRequest("Person_test");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.matchAllQuery());
        sourceBuilder.from(0);
        sourceBuilder.size(2);
        request.source(sourceBuilder);

        SearchResponse searchResponse = client.search(request, RequestOptions.DEFAULT);

        // 打印结果
        SearchHits hits = searchResponse.getHits();
        for (SearchHit hit : hits.getHits()) {
            System.out.println("Person = " + hit.getSourceAsString());
        }

        return searchResponse;
    }

    /**
     * 排序查询document
     * @throws IOException
     */
    @GetMapping("/sortQueryDocument")
    public SearchResponse sortQueryDocument() throws IOException {
        RestHighLevelClient client = elasticSearchClientConfig.restClient();
        SearchRequest request = new SearchRequest("Person_test");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.matchAllQuery());
        sourceBuilder.sort("age", SortOrder.ASC);
        request.source(sourceBuilder);

        SearchResponse searchResponse = client.search(request, RequestOptions.DEFAULT);

        // 打印结果
        SearchHits hits = searchResponse.getHits();
        for (SearchHit hit : hits.getHits()) {
            System.out.println("Person = " + hit.getSourceAsString());
        }

        return searchResponse;
    }

    /**
     * 条件查询document
     * @throws IOException
     */
    @GetMapping("/conditionQueryDocument")
    public SearchResponse conditionQueryDocument() throws IOException {
        RestHighLevelClient client = elasticSearchClientConfig.restClient();
        SearchRequest request = new SearchRequest("Person_test");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.matchAllQuery());
        sourceBuilder.sort("age", SortOrder.ASC);
        sourceBuilder.fetchSource(new String[]{"name", "age"}, null);
        request.source(sourceBuilder);

        SearchResponse searchResponse = client.search(request, RequestOptions.DEFAULT);

        // 打印结果
        SearchHits hits = searchResponse.getHits();
        for (SearchHit hit : hits.getHits()) {
            System.out.println("Person = " + hit.getSourceAsString());
        }

        return searchResponse;
    }

    /**
     * 组合查询  must是必须满足所有条件，should只要满足一个就行
     * @throws IOException
     */
    @GetMapping("/combinationQueryDocument")
    public SearchResponse combinationQueryDocument() throws IOException {
        RestHighLevelClient client = elasticSearchClientConfig.restClient();
        SearchRequest request = new SearchRequest("Person_test");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.boolQuery()
                .must(QueryBuilders.matchQuery("age", 21))
                .must(QueryBuilders.matchQuery("sex", "男"))
                .mustNot(QueryBuilders.matchQuery("sex", "女")));
        request.source(sourceBuilder);

        SearchResponse searchResponse = client.search(request, RequestOptions.DEFAULT);

        // 打印结果
        SearchHits hits = searchResponse.getHits();
        for (SearchHit hit : hits.getHits()) {
            System.out.println("Person = " + hit.getSourceAsString());
        }

        return searchResponse;
    }

    /**
     * 范围查询
     * @throws IOException
     */
    @GetMapping("/scopeQueryDocument2")
    public SearchResponse scopeQueryDocument2() throws IOException {
        RestHighLevelClient client = elasticSearchClientConfig.restClient();
        SearchRequest request = new SearchRequest("Person_test");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.rangeQuery("age").gte(20).lt(21));
        request.source(sourceBuilder);

        SearchResponse searchResponse = client.search(request, RequestOptions.DEFAULT);

        // 打印结果
        SearchHits hits = searchResponse.getHits();
        for (SearchHit hit : hits.getHits()) {
            System.out.println("Person = " + hit.getSourceAsString());
        }

        return searchResponse;
    }

    /**
     * 模糊查询
     * @throws IOException
     */
    @GetMapping("/fuzzyQueryDocument2")
    public SearchResponse fuzzyQueryDocument2() throws IOException {
        RestHighLevelClient client = elasticSearchClientConfig.restClient();
        SearchRequest request = new SearchRequest("Person_test");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.fuzzyQuery("name", "tst"));
        request.source(sourceBuilder);

        SearchResponse searchResponse = client.search(request, RequestOptions.DEFAULT);

        // 打印结果
        SearchHits hits = searchResponse.getHits();
        for (SearchHit hit : hits.getHits()) {
            System.out.println("Person = " + hit.getSourceAsString());
        }

        return searchResponse;
    }

    /**
     * 高亮查询
     * @throws IOException
     */
    @GetMapping("/highlightQueryDocument2")
    public SearchResponse highlightQueryDocument2() throws IOException {
        RestHighLevelClient client = elasticSearchClientConfig.restClient();
        SearchRequest request = new SearchRequest("Person_test");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.termQuery("name", "test4"));
        sourceBuilder.highlighter(new HighlightBuilder().field("name").preTags("<font color='red'>").postTags("</font>"));
        request.source(sourceBuilder);

        SearchResponse searchResponse = client.search(request, RequestOptions.DEFAULT);

        // 打印结果
        SearchHits hits = searchResponse.getHits();
        for (SearchHit hit : hits.getHits()) {
            System.out.println("Person = " + hit.getSourceAsString());
        }

        return searchResponse;
    }

    /**
     * 聚合查询
     * @throws IOException
     */
    @GetMapping("/aggregateQueryDocument2")
    public SearchResponse aggregateQueryDocument2() throws IOException {
        RestHighLevelClient client = elasticSearchClientConfig.restClient();
        SearchRequest request = new SearchRequest("Person_test");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.aggregation(AggregationBuilders.max("maxAge").field("age"));

        request.source(sourceBuilder);

        SearchResponse searchResponse = client.search(request, RequestOptions.DEFAULT);

        // 打印结果
        org.elasticsearch.search.aggregations.Aggregations aggregations = searchResponse.getAggregations();
        org.elasticsearch.search.aggregations.metrics.Max maxAge = aggregations.get("maxAge");
        System.out.println("Max Age: " + maxAge.getValue());

        return searchResponse;
    }

    /**
     * 分组查询
     * @throws IOException
     */
    @GetMapping("/groupQueryDocument2")
    public SearchResponse groupQueryDocument2() throws IOException {
        RestHighLevelClient client = elasticSearchClientConfig.restClient();
        SearchRequest request = new SearchRequest("Person_test");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.aggregation(AggregationBuilders.terms("ageGroup").field("age"));
        request.source(sourceBuilder);

        SearchResponse searchResponse = client.search(request, RequestOptions.DEFAULT);

        // 打印结果
        Aggregations aggregations = searchResponse.getAggregations();
        ParsedTerms ageGroup = aggregations.get("ageGroup");
        for (Bucket entry : ageGroup.getBuckets()) {
            System.out.println("Age:"+entry.getKeyAsString() + "Count: " + entry.getDocCount() );
        }

        return searchResponse;
    }
}